//
// Unihan Input Method
//
// Copyright © 2002-2007 Sun Wah Linux Ltd.
//
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
// USA
//
// $Id: frequence.c 757 2007-05-10 08:19:31Z roger $
//


#include <stdio.h>
#include <unihan_im.h>

#include "frequence.h"
#include "table.h"

static void
freq_post(UnihanIM *uim, int id);

int
freq_init(UnihanIM *uim)
{
	return 1;
}

/* get all candidates and sort them, put result in freqCandList */
void
freq_sort(UnihanIM *uim)
{
	TableDataPerDesktop *dd = (TableDataPerDesktop *)uim->desktopUserData;
	TableDataPerSession *ds = (TableDataPerSession *)uim->sessionUserData;
	FreqCandList *candlist = NULL;
	int numCands = 0;
	int i,j;

	if (ds->numCands < 2)
		return;
	if (ds->frqCandList) {
		free(ds->frqCandList);
		candlist = ds->frqCandList = NULL;
	}
	candlist = ds->frqCandList = (FreqCandList *)malloc(ds->numCands * sizeof(FreqCandList));
	numCands = ds->numCands;

	for (i=ds->lowIdx; i<ds->highIdx; i++)
		candlist[i - ds->lowIdx].id = i - ds->lowIdx;

	for (i=numCands; i>1; i--)
		for(j=0; j<i-1; j++) {
			int prio1, prio2;
			int id, index;
			int id2, index2;
			FreqCandList frqtmp;
			
			id = candlist[j].id;
			index = ds->lowIdx + id;
			prio1 = dd->frqList[dd->kvtab[index].frqOff];
			
			id2 = candlist[j+1].id;
			index2 = ds->lowIdx + id2;
			prio2 = dd->frqList[dd->kvtab[index2].frqOff];

			if ((prio1 < prio2) && !strcmp(dd->keyList + dd->kvtab[index].keyOff, dd->keyList + dd->kvtab[index2].keyOff)) {
				frqtmp.id = candlist[j].id;
				candlist[j].id = candlist[j+1].id;
				candlist[j+1].id = frqtmp.id;
			}
		}
}

int
freq_idx_search(UnihanIM *uim)
{
	TableDataPerDesktop *dd = (TableDataPerDesktop *)uim->desktopUserData;
	TableDataPerSession *ds = (TableDataPerSession *)uim->sessionUserData;
	int index;

	index = ds->lowIdx + ds->frqCandList[ds->luCurrCandOffset].id;
	freq_post(uim, ds->luCurrCandOffset);

	return index;
}


int
freq_idx_sel(UnihanIM *uim, IMKeyEvent *kev)
{
	TableDataPerDesktop *dd = (TableDataPerDesktop *)uim->desktopUserData;
	TableDataPerSession *ds = (TableDataPerSession *)uim->sessionUserData;
	int index;
	int realIdx, pageStart;

	pageStart = (ds->luCurrCandOffset / 9) * 9;
	realIdx = pageStart + kev->keyChar - '1';
	if (realIdx >= ds->highIdx) {
		uim->m->beep(uim);
		return TRUE;
	}

	index = ds->lowIdx + ds->frqCandList[realIdx].id;
	freq_post(uim, realIdx);
	return index;
}

static void
freq_post(UnihanIM *uim, int idx)
{
	TableDataPerDesktop *dd = (TableDataPerDesktop *)uim->desktopUserData;
	TableDataPerSession *ds = (TableDataPerSession *)uim->sessionUserData;
	int lowIdx, highIdx;
	int curroff = dd->kvtab[ds->lowIdx + ds->frqCandList[idx].id].frqOff;
	int currmaxoff = dd->kvtab[ds->lowIdx + ds->frqCandList[idx].id].maxFrqOff;
	int frq;

	if (idx == 0)
		return;
	if (dd->maxFrqList[currmaxoff] < 0)
		return;
	lowIdx = idx - 1;
	//highIdx = idx + 1;

	while (lowIdx) {
		if (strcmp(dd->keyList + dd->kvtab[ds->lowIdx + ds->frqCandList[lowIdx].id].keyOff,
			dd->keyList + dd->kvtab[ds->lowIdx + ds->frqCandList[lowIdx + 1].id].keyOff) != 0)
			break;
		lowIdx--;
	}
	if (lowIdx)
		lowIdx++;

	frq = dd->frqList[curroff] + ds->frqAppend;

	highIdx = idx - 1;
	while (highIdx - lowIdx) {
		if (dd->frqList[dd->kvtab[ds->lowIdx + ds->frqCandList[highIdx].id].frqOff] >= frq)
			break;
		else {
			int index = dd->kvtab[ds->lowIdx + ds->frqCandList[highIdx].id].frqOff;
			dd->frqList[index] -= PRIO_CELL;
			if (dd->frqList[index] < 0)
				dd->frqList[index] = 0;
			highIdx--;
		}
	}
	if (frq > dd->maxFrqList[currmaxoff])
		frq = dd->maxFrqList[currmaxoff];
	dd->frqList[curroff] = frq;
}

// vi:ts=4:nowrap:cin:expandtab
